// freeContent
/////////////////////////////////////////////

(function ($, undefined) {

    // define the name of the UI component
    var ui_name = "freeContent"

    // initialize object
    var fc = $.freeContent = {

        // default values
        defaults: {
            displayDelay: 10,
            direction: 'bottom',  // 方向： top, bottom, left, right
            align: 'left',  // todo: 对齐方式： left, aligh, right (left == up, right == down)
            showArrow: false,

            content: null,
        },

        setDefaults: function (defaultOptions) {
            this.defaults = $.extend({}, this.defaults, defaultOptions);
        }
    };

    $.fn.freeContent = function (options) {

        // method calling
        if (typeof options == 'string') {
            var args = Array.prototype.slice.call(arguments, 1),
			res;
            this.each(function () {
                var data = $.data(this, ui_name);
                if (data) {
                    var meth = data[options];
                    if (meth) {
                        var r = meth.apply(this, args);
                        if (res === undefined) {
                            res = r;
                        }
                    }
                }
            });
            if (res !== undefined) {
                return res;
            }
            return this;
        }

        // initialize options
        options = $.extend({}, fc.defaults, options);

        this.each(function () {
            var _self = this;

            // initialize callback
            for (var key in options) {
                var value = options[key];
                if (typeof value == 'function') {
                    // bind callbacks
                    $(_self).bind(key, value);
                }
            }

            var contentDisplayed = false,
                mouseCaptured = false,
                targetElement = $(this),
                content = $(options.content),
                targetElementCover,
                arrowCover;

            /* Public Methods
            -----------------------------------------------------------------------------*/

            var publicMethods = {
                option: function (name, value) {
                    if (value === undefined) {
                        return options[name];
                    }
                    options[name] = value;
                },
                close: function () {
                    contentDisplayed = true;
                    mouseCaptured = false;
                    freeContentLeave();
                }
                   
            };

            $.data(this, ui_name, publicMethods);

            
            /* Private Methods
            -----------------------------------------------------------------------------*/

            var setTargetElementStyle = function () {
                $(targetElement)
                    .addClass("freecontent-targetelement")
                    .mouseenter(function () { mouseCaptured = true; })
                    .mouseleave(function () {
                        mouseCaptured = false;
                        setTimeout(freeContentLeave, options.displayDelay);
                    })
                    .addClass("freecontent-targetelement-mouseover");

                var height = $(targetElement).innerHeight();
                var width = $(targetElement).innerWidth();
                var left = $(targetElement).offset().left;
                var top = $(targetElement).offset().top;

                targetElementCover = $('<div/>')
                  .attr('id', $(content).attr('id')) 
                  .addClass('freecontent-targetelement-cover')
                  .css({
                      'height': height,
                      'width': width,
                      'top': top,
                      'left': left
                  })
                  .mouseenter(function () { mouseCaptured = true; })
                  .mouseleave(function () {
                      mouseCaptured = false;
                      setTimeout(freeContentLeave, options.displayDelay);
                  })
                  .appendTo('body');

            };

            var setContentPositionAndStyle = function (position) {

                var desireLeft = position.left;
                var desireTop = position.top;

                switch (options.direction) {
                    case 'top':
                        targetElementCover.css({ 'border-top-color': 'transparent' });
                        desireTop = desireTop - content.outerHeight() ;
                        break;
                    case 'bottom':
                        targetElementCover.css({ 'border-bottom-color': 'transparent' });
                        desireTop = desireTop + targetElement.outerHeight() - 1;
                        break;
                    case 'left':
                        targetElementCover.css({ 'border-left-color': 'transparent' });
                        desireLeft = desireLeft - content.outerWidth() + 1;
                        desireTop --;
                        break;
                    case 'right':
                        targetElementCover.css({ 'border-right-color': 'transparent' });
                        desireLeft = desireLeft + targetElement.outerWidth() - 1;
                        desireTop --;
                        break;
                }

                if (options.align == 'right') {
                    if (options.direction == 'bottom') {
                        desireLeft = desireLeft - content.outerWidth() + targetElement.outerWidth();
                    }
                }

                $(content)
                    .css({
                        left: desireLeft + "px",
                        top: desireTop + "px"
                    })
                    .mouseenter(function () { mouseCaptured = true; })
                    .mouseleave(function () {
                        mouseCaptured = false;
                        setTimeout(freeContentLeave, options.displayDelay);
                    })
                    .fadeIn();

                if (options['showArrow'] && arrowCover) {
                    // 将箭头设置为 向上
                    $(arrowCover)
                          .removeClass('ui-icon-triangle-1-s')
                          .addClass('ui-icon-triangle-1-n')
                }
            };

            var freeContentHover = function () {
                if (!contentDisplayed) {
                    mouseCaptured = true;
                    contentDisplayed = true;

                    var position = $(targetElement).offset();
                    setTargetElementStyle();
                    setContentPositionAndStyle(position);
                }
            };


            var freeContentLeave = function () {
                if (contentDisplayed && !mouseCaptured) {
                    $(targetElement).removeClass("freecontent-targetelement-mouseover");
                    $(targetElementCover).remove();
                    $(content).hide();

                    if (options['showArrow'] && arrowCover) {
                        // 将箭头设置为 向下
                        $(arrowCover)

                          .removeClass('ui-icon-triangle-1-n')
                          .addClass('ui-icon-triangle-1-s')
                    }

                    contentDisplayed = false;
                }
            };


            var setArrowCoverToTargetElement = function (targetElement) {
                if (!arrowCover) {
                    arrowCover = getNewArrowCover();
                }
                var position = $(targetElement).offset();
                // 为箭头布局
                var desireLeft = position.left + targetElement.innerWidth() - arrowCover.innerWidth();
                var desireTop = position.top + (targetElement.innerHeight() - arrowCover.innerHeight()) / 2;

                arrowCover.css({
                    'left': desireLeft + "px",
                    'top': desireTop + "px"
                });
            }

            function hideTargetContent() {
                $(content)
                  .addClass('freecontent-content')
                  .hide();
            }

            function InitializeContent() {
                hideTargetContent();
                $(targetElement)
				.addClass('freecontent-targetelement')
				.hover(
                    freeContentHover
                );
                // 给覆盖层加上向下箭头
                if (options["showArrow"]) {
                    setArrowCoverToTargetElement(targetElement);

                    // such a stupid method
                    // 为了保证箭头位置准确，不断的重绘
                    setInterval(function () {
                        setArrowCoverToTargetElement(targetElement);
                    }, 50);

                    // 窗体大小变化时，自动重绘箭头
                    $(window).wresize(function () {
                        setArrowCoverToTargetElement(targetElement);
                    });

                    arrowCover.hover(
                        freeContentHover
                    );
                }
             }


             // ok, let's begin
             InitializeContent();

        });

        return this;
    };


    /* Static Methods
    -----------------------------------------------------------------------------*/
    var getNewArrowCover = function () {
        return $('<span/>')
            .addClass('ui-icon ui-icon-triangle-1-s')
            .css({
                'position': 'absolute',
                'cursor': 'pointer'
            })
            .appendTo('body');
    };


})(jQuery);



